package com.xtaller.sdboot.core.generator;

import com.xtaller.sdboot.utils.helper.StrHelper;
import com.xtaller.sdboot.utils.helper.TimeHelper;
import lombok.var;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;

/**
 * @author: Taller
 * @date:   2020-03-17
 * @version V1.0
 * @Description: 生成代码
 */
public class Code {
	/**
	 * 创建VO
	 * */
	public static StringBuffer createVo(
			String module,
			String model,
			String description,
			ResultSet column) {
		StringBuffer sb = new StringBuffer();
		sb.append("package com.xtaller.soda.vo." + module +"; \n \n");
		sb.append("import io.swagger.annotations.ApiModel; \n");
		sb.append("import io.swagger.annotations.ApiModelProperty; \n");
		sb.append("import lombok.Data; \n");
		sb.append("import lombok.AllArgsConstructor; \n");
		sb.append("import lombok.NoArgsConstructor; \n");
		sb.append("/** \n");
		sb.append("* 代码生成 \n");
		sb.append("* @author: Taller  \n");
		sb.append("* @date: " + TimeHelper.formatNow("yyyy-MM-dd HH:mm:ss") + "\n");
		sb.append("* @Description: " + description + " \n");
		sb.append("*/ \n");
		sb.append("@Data \n@NoArgsConstructor\n" +
				"@AllArgsConstructor \n");
		sb.append("@ApiModel(value = \"" + description + "-VO\") \n");
		sb.append("public class " + model +"VO { \n");
		try {
			while (column.next()) {
				sb.append(createVOGS(column.getString(2), column.getString(1), column.getString(3)));
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		sb.append("} \n");
		return sb;
	}

	/**
	 * 创建mapping映射的实体
	 * */
	public static StringBuffer createModel(
			String packages,
			String model,
			String description,
			ResultSet column) {
		StringBuffer sb = new StringBuffer();
		sb.append("package " + packages + ";\n\n");
		sb.append("import com.baomidou.mybatisplus.annotation.TableField; \n");
		sb.append("import com.xtaller.sdboot.core.base.BaseEntity; \n");
		sb.append("import org.hibernate.validator.constraints.Length; \n");
		sb.append("import javax.validation.constraints.NotNull; \n");
		sb.append("import lombok.Data; \n");
		sb.append("/** \n");
		sb.append("* 代码生成 \n");
		sb.append("* @author: Taller  \n");
		sb.append("* @date: " + TimeHelper.formatNow("yyyy-MM-dd HH:mm:ss") + "\n");
		sb.append("* @Description: " + description + " \n");
		sb.append("*/ \n");
		sb.append("@Data \n");
		sb.append("public class " + model +" extends BaseEntity { \n");
		try {
			while (column.next()) {
				var code = createGetSet(column.getString(2), column.getString(1), column.getString(3));
				if(code != null) {
					sb.append(code);
				}
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		sb.append("} \n");
		return sb;
	}

	// 创建Mapper
	public static StringBuffer createMapper(String packages,
											String modelPath,
											String model,
											String description){
		StringBuffer sb = new StringBuffer();
		sb.append("package " + packages + ";\n\n");
		sb.append("import com.baomidou.mybatisplus.core.mapper.BaseMapper; \n");
		sb.append("import " + modelPath + "." + model + "; \n");
		sb.append("/** \n");
		sb.append("* 代码生成 \n");
		sb.append("* @author: Taller  \n");
		sb.append("* @date: " + TimeHelper.formatNow("yyyy-MM-dd HH:mm:ss") + "\n");
		sb.append("* @Description: " + description + " \n");
		sb.append("*/ \n");

		sb.append("public interface " + model +"Mapper extends BaseMapper<"+ model +"> { \n");
		sb.append("} \n");
		return sb;
	}

	private static StringBuffer createGetSet(String type, String field, String context) {
		if(!excludes(field)) {
			StringBuffer sb = new StringBuffer();
			sb.append("    // " + context + " \n");
			sb.append("    @TableField(value = \"" + field + "\") \n");
			if(type.equals("tinyint") ||
					type.equals("smallint") ||
					type.equals("int")) {
				sb.append("    private Integer " + StrHelper.toLowerCaseCamel(field) + ";\n");

			}else if(type.equals("bigint")) {
				sb.append("    private Long " + StrHelper.toLowerCaseCamel(field) + ";\n");
			}else if(type.equals("datetime")) {

			}else {	// varchar text
				sb.append("    private String " + StrHelper.toLowerCaseCamel(field) + ";\n");
			}
			sb.append("\n");
			return sb;
		}
		return null;
	}

	// 创建服务类接口
	public static StringBuffer createIService(
			String packages,
			String modelPath,
			String model,
			String description
	) {
		StringBuffer sb = new StringBuffer();
		sb.append("package " + packages + "; \n\n");
		sb.append("import " + modelPath + "."+ model + "; \n");
		sb.append("import com.xtaller.sdboot.core.base.BaseService; \n");
		sb.append(" \n");
		sb.append("/** \n");
		sb.append("* 代码生成 \n");
		sb.append("* @author: Taller  \n");
		sb.append("* @date: " + TimeHelper.formatNow("yyyy-MM-dd HH:mm:ss") + "\n");
		sb.append("* @Description: " + description + "服务接口 \n");
		sb.append("*/ \n");
		sb.append("public interface " + model + "Service extends BaseService<" + model + "> { \n");
		sb.append("}\n");

		return sb;
	}

	// 创建控制器
	public static StringBuffer createController(
			String packages,
			String modelPath,
			String servicePath,
			String model,
			String requestMapping,
			String description
	) {

		StringBuffer sb = new StringBuffer();
		sb.append("package " + packages + "; \n\n");
		sb.append("import " + modelPath + "."+ model + "; \n");
		sb.append("import " + servicePath + "."+ model + "Service; \n");
		sb.append("import com.xtaller.sdboot.utils.annotation.Permission; \n");
		sb.append("import org.springframework.beans.factory.annotation.Autowired;\n" +
				"import org.springframework.web.bind.annotation.PathVariable;\n" +
				"import org.springframework.web.bind.annotation.RequestBody;\n" +
				"import org.springframework.web.bind.annotation.RequestMapping;\n" +
				"import org.springframework.web.bind.annotation.RestController; \n" +
				"import com.xtaller.sdboot.core.base.BaseController;\n" +
				"import io.swagger.annotations.Api; \n" +
				"import io.swagger.annotations.ApiOperation; \n" +
				"import io.swagger.annotations.ApiParam;\n" +
				"\n" +
				"import javax.servlet.http.HttpServletRequest;\n" +
				"import javax.validation.Valid;\n" +
				"import java.io.Serializable; \n");

		sb.append(" \n");
		sb.append("/** \n");
		sb.append("* 代码生成 \n");
		sb.append("* @author: Taller  \n");
		sb.append("* @date: " + TimeHelper.formatNow("yyyy-MM-dd HH:mm:ss") + "\n");
		sb.append("* @Description: " + description + "控制器 \n");
		sb.append("*/ \n");
		sb.append("@Api(tags = \"" + description + "控制器\") \n");
		sb.append("@RestController \n");
		sb.append("@RequestMapping(\"" + requestMapping + "\") \n");
		sb.append("public class " + model + "Controller extends BaseController<" + model + "> { \n");
		sb.append("    @Autowired private " + model + "Service " + formatService(requestMapping) + "Service; \n");
		sb.append(" \n");
		sb.append("    @ApiOperation(\"表格\") \n");
		sb.append("    @Permission(authorities = \"" + formatPermission(requestMapping) + ":data:list\")\n");
		sb.append("    @Override\n");
		sb.append("    public Object getByPage(HttpServletRequest request) throws Exception {\n");
		sb.append("        return super.getByPage(request);\n");
		sb.append("    } \n");
		sb.append(" \n");
		sb.append("    @ApiOperation(\"创建\")\n");
		sb.append("    @Permission(authorities = \"" + formatPermission(requestMapping) + ":opt:create\")\n");
		sb.append("    @Override\n");
		sb.append("    public Object createEntity(@Valid @RequestBody " + model + " entity, HttpServletRequest request) throws Exception {\n");
		sb.append("        return super.createEntity(entity, request);\n");
		sb.append("    } \n");
		sb.append(" \n");
		sb.append("    @ApiOperation(\"修改\")\n");
		sb.append("    @Permission(authorities = \"" + formatPermission(requestMapping) + ":opt:update\") \n");
		sb.append("    @Override\n");
		sb.append("    public Object updateEntity(@PathVariable(\"id\") Serializable id, @Valid @RequestBody " + model + " entity, HttpServletRequest request) throws Exception {\n");
		sb.append("        return super.updateEntity(id, entity, request);\n");
		sb.append("    } \n");
		sb.append(" \n");
		sb.append("    @ApiOperation(\"删除\")\n");
		sb.append("    @Permission(authorities = \"" + formatPermission(requestMapping) + ":opt:delete\")\n");
		sb.append("    @Override\n");
		sb.append("    public Object deleteEntity(@PathVariable(\"id\") Serializable id, HttpServletRequest request) throws Exception {\n");
		sb.append("        return super.deleteEntity(id, request);\n");
		sb.append("    } \n");

		sb.append("}\n");

		return sb;
	}

	// 创建服务类接口
	public static StringBuffer createServiceImpl(
			String packages,
			String modelPath,
			String mapperPath,
			String servicePath,
			String model,
			String description
	) {
		StringBuffer sb = new StringBuffer();
		sb.append("package " + packages + "; \n\n");

		sb.append("import com.xtaller.sdboot.core.base.impl.BaseServiceImpl; \n");
		sb.append("import " + servicePath + "."+ model + "Service; \n");
		sb.append("import " + mapperPath + "."+ model + "Mapper; \n");
		sb.append("import " + modelPath + "."+ model + "; \n");
		sb.append("import lombok.extern.slf4j.Slf4j; \n");
		sb.append("import org.springframework.stereotype.Service; \n");
		sb.append(" \n");
		sb.append("/** \n");
		sb.append("* 代码生成 \n");
		sb.append("* @author: Taller  \n");
		sb.append("* @date: " + TimeHelper.formatNow("yyyy-MM-dd HH:mm:ss") + "\n");
		sb.append("* @Description: " + description + "服务实现 \n");
		sb.append("*/ \n");
		sb.append("@Service \n");
		sb.append("@Slf4j \n");
		sb.append("public class " + model + "ServiceImpl extends BaseServiceImpl<" + model + "Mapper, "+model+"> implements " + model + "Service { \n");
		sb.append("}\n");

		return sb;
	}

	private static StringBuffer createVOGS(String type, String field, String context) {

		StringBuffer sb = new StringBuffer();

		if(type.equals("tinyint") ||
				type.equals("smallint") ||
				type.equals("int")) {
			if(!excludes(field)) {
				sb.append("    @ApiModelProperty(value = \"" + context +"\") \n");
				sb.append("    private Integer " + field + ";\n");
				sb.append("\n");
			}
		}else if(type.equals("bigint")) {
			if(!excludes(field)) {
				sb.append("    @ApiModelProperty(value = \"" + context +"\") \n");
				sb.append("    private Long " + field + ";\n");
				sb.append("\n");
			}
		}else if(type.equals("datetime")) {

		}else {	// varchar text
			if(!excludes(field)) {
				sb.append("    @ApiModelProperty(value = \"" + context +"\") \n");
				sb.append("    private String " + field + ";\n");
				sb.append("\n");
			}
		}
		return sb;
	}

	private static boolean excludes(String attr){
		var items = Arrays.asList("isDeleted", "createBy", "id", "version", "ext", "updateTime", "createTime", "createId", "isDelete");
		var opt = items.stream().filter(x -> x.equals(attr)).findFirst();
		return opt.isPresent();
	}
	private static boolean excludes2(String attr){
		var items = Arrays.asList("isDeleted", "createBy", "appId", "id", "version", "ext", "updateTime", "createTime", "createId", "isDelete");
		var opt = items.stream().filter(x -> x.equals(attr)).findFirst();
		return opt.isPresent();
	}

	private static String formatField(String field){
		var items = field.split("_");
		var fileName = field.substring(0, 1).toUpperCase() + field.substring(1, field.length());
		return fileName;
	}


	/**
	 * 创建html页面
	 * */
	public static StringBuffer createHtml(String tableName){
		StringBuffer sb = new StringBuffer();
		sb.append("<div class=\"layui-fluid\" style=\"overflow-y: hidden;\"> \n");
		sb.append("    <div class=\"layui-card\"> \n");
		sb.append("        <div class=\"layui-card-body\"> \n");
		sb.append("            <div class=\"layui-form toolbar search-view\" id=\"" + tableName + "_search\"></div> \n");
		sb.append("            <table class=\"layui-table\" id=\"" + tableName + "_table\" lay-filter=\"" + tableName + "_table\"></table> \n");
		sb.append("        </div> \n");
		sb.append("    </div> \n");
		sb.append("</div> \n");
		sb.append("\n");
		var jsPath = "/controller/" + StrHelper.join(tableName.split("_"), "/") + ".js";

		sb.append("<script src=\"" + jsPath +"\"></script>");
		return sb;
	}

	/**
	 * 创建js
	 * */
	public static StringBuffer createJs(String tableName, String requestMapping, ResultSet c1, ResultSet c2){
		StringBuffer sb = new StringBuffer();
		sb.append("soda() \n");
		sb.append("\t._page('" + tableName + "') \n");
		sb.append("\t._api('" + requestMapping + "') \n");
		sb.append("\t._query([]) \n");
		sb.append("\t._orderBy(['createTime^desc']) \n");
		sb.append("\t._run((unit) => { \n");
		sb.append("\t\t// 表单配置 \n");
		sb.append("\t\tunit.templateForm['verify'] = []; \n");
		sb.append("\t\tunit.templateForm['items'] = [ \n");
		sb.append(createJsFormField(c2));
		sb.append("\t\t]; \n");
		sb.append(" \n");
		sb.append("\t\t// 表格基础配置 \n");
		sb.append("\t\tunit.templateTable['cols'] = [ \n");
		sb.append(createJsField(c1));
		sb.append("\t\t\t{field: 'createTime', title: '创建时间'}, \n");
		sb.append("\t\t\t{field: 'updateTime', title: '上次修改', templet(obj) { \n");
		sb.append("\t\t\t\tlet ct = obj.createTime; \n");
		sb.append("\t\t\t\tlet ut = obj.updateTime; \n");
		sb.append("\t\t\t\treturn ct == ut ? '' : ut; \n");
		sb.append("\t\t\t}}, \n");
		sb.append("\t\t\t{fixed: 'right', title: '操作', minWidth: 120, toolbar: unit.sysApplication['btns']['right']()} \n");
		sb.append("\t\t]; \n");
		sb.append("\t\tunit.templateTable['bar'] = (opt) => { \n");
		sb.append("\t\t\tunit.templateDialog[opt.event](); \n");
		sb.append("\t\t} \n");
		sb.append("\t\tunit.templateTable['tool'] = (opt) => { \n");
		sb.append("\t\t\tunit.templateDialog[opt.event](opt.data); \n");
		sb.append("\t\t} \n");
		sb.append("\t\t// 表格查询配置 \n");
		sb.append("\t\tunit.templateTable['search']['components'] = [ \n");
		sb.append("\t\t\t{code:1, name:\"key\", title:\"关键字\", placeholder:\"请输入要查询的关键字\"} \n");
		sb.append("\t\t] \n");
		sb.append("\t\tunit.templateTable['search']['submit'] = (data) => { \n");
		sb.append("\t\t\tunit.sdTable.reload(unit.el['table'], { \n");
		sb.append("\t\t\t\twhere: unit.sdFormat['query'](unit.filter['vo'], data) \n");
		sb.append("\t\t\t}); \n");
		sb.append("\t\t} \n");
		sb.append(" \n");
		sb.append("\t\t//弹出层 \n");
		sb.append("\t\tunit.templateDialog['form'] = (data) => { \n");
		sb.append("\t\t\tunit.sdDialog.form({ \n");
		sb.append("\t\t\t\ttitle: data ? '修改' : \"创建\", \n");
		sb.append("\t\t\t\theight: '500px', \n");
		sb.append("\t\t\t\tinit() { \n");
		sb.append("\t\t\t\t\tunit.sdForm['init']['form'](unit.templateForm, data); \n");
		sb.append("\t\t\t\t}, \n");
		sb.append("\t\t\t\topt(index) { \n");
		sb.append("\t\t\t\t\t// 获取form \n");
		sb.append("\t\t\t\t\tlet form = unit.sdForm['get'](unit.el['form'], unit.templateForm['verify']); \n");
		sb.append("\t\t\t\t\t// 校验数据\n");
		sb.append("\t\t\t\t\tif (!form.check) {\n");
		sb.append("\t\t\t\t\t\tunit.sdDialog['tips']['warning'](form.message);\n");
		sb.append("\t\t\t\t\t\treturn false;\n");
		sb.append("\t\t\t\t\t}\n");
		sb.append("\t\t\t\t\t// 数据处理\n");
		sb.append("\t\t\t\t\tlet val = form.data;\n");
		sb.append(" \n");
		sb.append("\t\t\t\t\tlet param = {\n");
		sb.append("\t\t\t\t\t\turl: unit.api['crud'],\n");
		sb.append("\t\t\t\t\t\tdata: val,\n");
		sb.append("\t\t\t\t\t\ttips: true,\n");
		sb.append("\t\t\t\t\t\tcallback: function() {\n");
		sb.append("\t\t\t\t\t\t\tunit.sdDialog['close'](index);\n");
		sb.append("\t\t\t\t\t\t\tunit.sdTable['reload'](unit.el.table);\n");
		sb.append("\t\t\t\t\t\t}\n");
		sb.append("\t\t\t\t\t}\n");
		sb.append("\t\t\t\t\t// 操作\n");
		sb.append("\t\t\t\t\tdata ? unit.sdHttp['put'](param, data.id) : unit.sdHttp['post'](param);\n");
		sb.append("\t\t\t\t} \n");
		sb.append("\t\t\t}) \n");
		sb.append("\t\t} \n");
		sb.append("\t\tunit.templateDialog['create'] = unit.templateDialog['form'];\n");
		sb.append("\t\tunit.templateDialog['update'] = unit.templateDialog['form'];\n");
		sb.append("\t\tunit.templateDialog['delete'] = (data) => {\n");
		sb.append("\t\t\tunit.sdDialog.confirm({\n");
		sb.append("\t\t\t\ttitle: \"是否要删除这条数据?\",\n");
		sb.append("\t\t\t\tsubmit() {\n");
		sb.append("\t\t\t\t\tlet param = {\n ");
		sb.append("\t\t\t\t\t\turl: unit.api['crud'],\n ");
		sb.append("\t\t\t\t\t\tcallback() {\n ");
		sb.append("\t\t\t\t\t\t\tunit.sdTable['reload'](unit.el.table)\n ");
		sb.append("\t\t\t\t\t\t}\n ");
		sb.append("\t\t\t\t\t}\n ");
		sb.append("\t\t\t\t\tunit.sdHttp['delete'](param, data.id);\n ");
		sb.append("\t\t\t\t}\n ");
		sb.append("\t\t\t});\n ");
		sb.append("\t\t}\n ");
		sb.append("\t\tunit.sdTable['render'](unit.templateTable);\n ");
		sb.append("\t}); ");
		return sb;
	}

	// 生成前端表格字段
	private static StringBuffer createJsField(ResultSet column) {
		StringBuffer sb = new StringBuffer();
		try {
			while (column.next()) {
				var field = column.getString(1);
				if (!excludes2(field)) {
					var f = StrHelper.toLowerCaseCamel(field);
					sb.append("\t\t\t{field: '" + f + "', title: '" + column.getString(3) + "', minWidth: 120}, \n");
				}
			}

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return sb;
	}

	private static StringBuffer createJsFormField(ResultSet column) {
		StringBuffer sb = new StringBuffer();
		try {
			while (column.next()) {
				var field = column.getString(1);
				if (!excludes2(field)) {
					var f = StrHelper.toLowerCaseCamel(field);
					var c = column.getString(3);
					sb.append("\t\t\t{code: 1, name: '" + f + "', title: '" + c + "', placeholder: '请填写" + c + "'}, \n");
				}
			}

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return sb;
	}


	public static void main(String[] args){
		var tableName = "/v1/demo/user";
		var jsPath = "";
		var item = Arrays.asList(tableName.split("/"));
		var p = new ArrayList<String>();
		for(var i= 2; i< item.size() ; i++){
			p.add(item.get(i));
		}
		System.err.println(formatService(tableName));
	}
	private static String formatPermission(String rm){
		var item = Arrays.asList(rm.split("/"));
		var p = new ArrayList<String>();
		for(var i= 2; i< item.size() ; i++){
			p.add(item.get(i));
		}
		return StrHelper.join(p, ":");
	}

	private static String formatService(String rm){
		var item = Arrays.asList(rm.split("/"));
		var p = new ArrayList<String>();
		var name = "";
		for(var i= 2; i< item.size() ; i++){
			if(i == 2){
				name += item.get(i);
			}else{
				name += StrHelper.capFirst(item.get(i));
			}
		}

		return name;
	}
}
